package it.polito.let.filesystem;

import it.polito.let.jhp.JHPCompiler;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.logging.Logger;

public class FileUtil {
	private static Random rand = new Random();
	/**
	 * ritorna vero se f1 è più giovane di f2
	 */
	public static boolean isOlder(File f1, File f2) {
		return f1.lastModified() > f2.lastModified();
	}

	public static String randomFileName(String path, String ext, boolean getExt) {
		String name;
		File probe;
		do {
			name = "JHPPage"+Long.toString(Math.abs(rand.nextLong()), 36);
			if (ext != null)
				probe = new File(path,name+"."+ext);
			else
				probe = new File(path,name);
			//System.out.println("probing: "+probe.getPath());
		} while(probe.exists());
		return (ext !=null && getExt) ? name+"."+ext : name;
	}

	public static File compile(File f, String destPath) throws FileGenericError, FileNotFoundException {
		StringTokenizer strtk = new StringTokenizer(f.getName(), ".");
		String ext = null;

		while (strtk.hasMoreTokens())
			ext = strtk.nextToken();

		if (ext.compareToIgnoreCase(FileConstants.JAVASRC) == 0)
			return compileJava(f, destPath);
		if (ext.compareToIgnoreCase(FileConstants.JHPSRC) == 0)
			return compileJhp(f, destPath);

		throw new FileNotFoundException("Cannot treat such file extension: ."+ext);
	}

	private static File compileJhp(File f, String path) throws FileGenericError, FileNotFoundException {
		Logger.getLogger("it.polito.let.jhpserver").info("Compilo jhp source "+f.getName());
		File javaFile = JHPCompiler.compile(f);
		return compileJava(javaFile, path);
	}

	@SuppressWarnings("static-access")
	private static File compileJava(File f, String destPath) throws FileGenericError, FileNotFoundException {
		com.sun.tools.javac.Main javac = new com.sun.tools.javac.Main();
		String[] options;

		if (!f.exists() || !f.canRead())
			throw new FileNotFoundException("Error while compiling file "
					+ f.getPath() + "\nSource file does not exist.");

		options = new String[] { "-d", destPath, f.getAbsolutePath() };
		int i=1;
		try {
			i = javac.compile(options);
		} catch (Exception e) {
			throw new FileGenericError("Error while compiling file: "
					+ f.getPath());
		}

		if (i != 0)
			throw new FileGenericError("Error while compiling file: "
					+ f.getPath());


		String pkgPath = readPackageDeclaration(f).replace(".",File.separator);
		String s = destPath+File.separator+pkgPath+File.separator+f.getName();
		String s1 = changeFileExtension(s, FileConstants.JAVABIN);

		File binary = new File(s1);
		if (!binary.exists() || !binary.canRead())
			throw new FileGenericError("Error while compiling file "
					+ f.getPath() + "\nNo binary produced.");

		//	Keep java artifacts only if user requested to
		if (!System.getProperty("jhp.server.keep.artifacts", "false").equalsIgnoreCase("true"))
			f.delete();

		return binary;
	}

	public static String changeFileExtension(String fname, String newExt) {
		int lastDot = fname.lastIndexOf('.');
		if (lastDot == -1) {
			return (newExt==null) ? fname : fname+"." + newExt;
		}
		return  (newExt==null) ? fname.substring(0, lastDot) : fname.substring(0, lastDot) + "." + newExt;
	}

	private static String readPackageDeclaration(File f) {
		BufferedReader reader;
		String line;
		try {
			reader = new BufferedReader(new FileReader(f));
			while ((line = readStatement(reader)) != null) {
				//System.out.println(line);
				if (line.trim().toLowerCase()
						.matches("^package\\s+"+FileConstants.pkgRegexp+"$")) {
					return line.replace("package", "").replaceAll("\\s*", "");
				}
			}
			reader.close();
		} catch (IOException e) {
			//System.out.println("IOEX");
			return "";
		}
		//System.out.println("nf");
		return "";
	}

	private static String readStatement (BufferedReader r) throws IOException {
		StringBuffer buf = new StringBuffer();
		String line;
		int i;
		while (true) {
			if ((line = r.readLine()) == null)	return null;
			if ((i=line.indexOf(';'))==-1)	buf.append(line);
			else {
				buf.append(line.substring(0, i));
				break;
			}
		}
		return buf.toString();
	}

	public static String classnameToFilepath (String fullyqualifiedName) throws FileGenericError {
		if (!fullyqualifiedName.matches(FileConstants.pkgRegexp))
			throw new FileGenericError("Malformed fully-qualified class name: "+fullyqualifiedName);
		return fullyqualifiedName.replaceAll("\\s*", "").replace(".",File.separator)+"."+FileConstants.JAVASRC;
	}

	public static String FileExtension(String fname) {
		int lastDot = fname.lastIndexOf('.');
		if (lastDot == -1) {
			return "";
		}
		return fname.substring(lastDot+1);
	}

}
